import Vue from 'vue'
import types from '../../mutation-types'
import ConversationApi from '../../../api/inbox/conversation'
import MessageApi from '../../../api/inbox/message'
import { MESSAGE_STATUS, MESSAGE_TYPE } from '@/yichat.web.share/constants/messages'
import { createPendingMessage } from '@/helper/commons'
import {
  buildConversationList,
  isOnMentionsView,
  isOnUnattendedView,
} from './helpers/actionHelpers'
import messageReadActions from './actions/messageReadActions'
import AnalyticsHelper from '../../../helper/AnalyticsHelper'
import { CONVERSATION_EVENTS } from '../../../helper/AnalyticsHelper/events'
// actions
const actions = {
  getConversation: async ({ commit }, conversationId) => {
    try {
      const response = await ConversationApi.show(conversationId)
      commit(types.UPDATE_CONVERSATION, response.data)
      commit(`contacts/${types.SET_CONTACT_ITEM}`, response.data.meta.sender)
    } catch (error) {
      // Ignore error
    }
  },

  fetchAllConversations: async ({ commit, dispatch }, params) => {
    commit(types.SET_LIST_LOADING_STATUS)
    try {
      const {
        data: { data },
      } = await ConversationApi.get(params)

      buildConversationList(
        { commit, dispatch },
        params,
        data,
        params.assigneeType
      )
    } catch (error) {
      // Handle error
    }
  },

  fetchFilteredConversations: async ({ commit, dispatch }, params) => {
    commit(types.SET_LIST_LOADING_STATUS)
    try {
      const { data } = await ConversationApi.filter(params)
      buildConversationList(
        { commit, dispatch },
        params,
        data,
        'appliedFilters'
      )
    } catch (error) {
      // Handle error
    }
  },

  emptyAllConversations ({ commit }) {
    commit(types.EMPTY_ALL_CONVERSATION)
  },

  clearSelectedState ({ commit }) {
    commit(types.CLEAR_CURRENT_CHAT_WINDOW)
  },

  fetchPreviousMessages: async ({ commit }, data) => {
    try {
      const {
        data: { meta, payload },
      } = await MessageApi.getPreviousMessages(data)
      commit(`conversationMetadata/${types.SET_CONVERSATION_METADATA}`, {
        id: data.conversationId,
        data: meta,
      })
      commit(types.SET_PREVIOUS_CONVERSATIONS, {
        id: data.conversationId,
        data: payload,
      })
      if (payload.length < 20) {
        commit(types.SET_ALL_MESSAGES_LOADED)
      }
    } catch (error) {
      // Handle error
    }
  },

  async setActiveChat ({ commit, dispatch }, data) {
    commit(types.SET_CURRENT_CHAT_WINDOW, data)
    commit(types.CLEAR_ALL_MESSAGES_LOADED)

    if (data.dataFetched === undefined) {
      try {
        await dispatch('fetchPreviousMessages', {
          conversationId: data.id,
          before: data.messages[0].createdAt,
        })
        Vue.set(data, 'dataFetched', true)
      } catch (error) {
        // Ignore error
      }
    }
  },

  assignAgent: async ({ dispatch }, { conversationId, agentId }) => {
    try {
      const response = await ConversationApi.assignAgent({
        conversationId,
        agentId,
      })
      dispatch('setCurrentChatAssignee', response.data)
    } catch (error) {
      // Handle error
    }
  },

  setCurrentChatAssignee ({ commit }, assignee) {
    commit(types.ASSIGN_AGENT, assignee)
  },

  assignTeam: async ({ dispatch }, { conversationId, teamId }) => {
    try {
      const response = await ConversationApi.assignTeam({
        conversationId,
        teamId,
      })
      dispatch('setCurrentChatTeam', { team: response.data, conversationId })
    } catch (error) {
      // Handle error
    }
  },

  setCurrentChatTeam ({ commit }, { team, conversationId }) {
    commit(types.ASSIGN_TEAM, { team, conversationId })
  },

  toggleStatus: async (
    { commit },
    { conversationId, status, snoozedUntil = null }
  ) => {
    try {
      const {
        data: {
          payload: {
            currentStatus: updatedStatus,
            snoozedUntil: updatedSnoozedUntil,
          } = {},
        } = {},
      } = await ConversationApi.toggleStatus({
        conversationId,
        status,
        snoozedUntil,
      })
      commit(types.CHANGE_CONVERSATION_STATUS, {
        conversationId,
        status: updatedStatus,
        snoozedUntil: updatedSnoozedUntil,
      })
    } catch (error) {
      // Handle error
    }
  },

  createPendingMessageAndSend: async ({ dispatch }, data) => {
    const pendingMessage = createPendingMessage(data)
    dispatch('sendMessageWithData', pendingMessage)
  },

  sendMessageWithData: async ({ commit }, pendingMessage) => {
    try {
      commit(types.ADD_MESSAGE, {
        ...pendingMessage,
        status: MESSAGE_STATUS.PROGRESS,
      })
      const response = await MessageApi.create(pendingMessage)
      AnalyticsHelper.track(
        pendingMessage.private
          ? CONVERSATION_EVENTS.SENT_PRIVATE_NOTE
          : CONVERSATION_EVENTS.SENT_MESSAGE
      )
      commit(types.ADD_MESSAGE, {
        ...response.data,
        status: MESSAGE_STATUS.SENT,
      })
    } catch (error) {
      const errorMessage = error.response
        ? error.response.data.error
        : undefined
      commit(types.ADD_MESSAGE, {
        ...pendingMessage,
        meta: {
          error: errorMessage,
        },
        status: MESSAGE_STATUS.FAILED,
      })
      throw error
    }
  },

  addMessage ({ commit }, message) {
    commit(types.ADD_MESSAGE, message)
    if (message.messageType === MESSAGE_TYPE.INCOMING) {
      commit(types.SET_CONVERSATION_CAN_REPLY, {
        conversationId: message.conversationId,
        canReply: true,
      })
    }
  },

  updateMessage ({ commit }, message) {
    commit(types.ADD_MESSAGE, message)
  },

  deleteMessage: async function deleteLabels (
    { commit },
    { conversationId, messageId }
  ) {
    try {
      const response = await MessageApi.delete(conversationId, messageId)
      const { data } = response
      // The delete message is actually deleting the content.
      commit(types.ADD_MESSAGE, data)
    } catch (error) {
      throw new Error(error)
    }
  },

  addConversation ({ commit, state, dispatch, rootState }, conversation) {
    const { currentInbox, appliedFilters } = state
    const {
      inboxId: inboxId,
      meta: { sender },
    } = conversation

    const hasAppliedFilters = !!appliedFilters.length
    const isMatchingInboxFilter =
      !currentInbox || currentInbox === inboxId
    if (
      !hasAppliedFilters &&
      !isOnMentionsView(rootState) &&
      !isOnUnattendedView(rootState) &&
      isMatchingInboxFilter
    ) {
      commit(types.ADD_CONVERSATION, conversation)
      dispatch('contacts/setContact', sender)
    }
  },

  addMentions ({ dispatch, rootState }, conversation) {
    if (isOnMentionsView(rootState)) {
      dispatch('updateConversation', conversation)
    }
  },

  addUnattended ({ dispatch, rootState }, conversation) {
    if (isOnUnattendedView(rootState)) {
      dispatch('updateConversation', conversation)
    }
  },

  updateConversation ({ commit, dispatch }, conversation) {
    const {
      meta: { sender },
    } = conversation
    commit(types.UPDATE_CONVERSATION, conversation)

    dispatch('conversationLabels/setConversationLabel', {
      id: conversation.id,
      data: conversation.labels,
    })

    dispatch('contacts/setContact', sender)
  },

  setChatFilter ({ commit }, data) {
    commit(types.CHANGE_CHAT_STATUS_FILTER, data)
  },

  updateAssignee ({ commit }, data) {
    commit(types.UPDATE_ASSIGNEE, data)
  },

  updateConversationContact ({ commit }, data) {
    if (data.id) {
      commit(`contacts/${types.SET_CONTACT_ITEM}`, data)
    }
    commit(types.UPDATE_CONVERSATION_CONTACT, data)
  },

  setActiveInbox ({ commit }, inboxId) {
    commit(types.SET_ACTIVE_INBOX, inboxId)
  },

  muteConversation: async ({ commit }, conversationId) => {
    try {
      await ConversationApi.mute(conversationId)
      commit(types.MUTE_CONVERSATION)
    } catch (error) {
      //
    }
  },

  unmuteConversation: async ({ commit }, conversationId) => {
    try {
      await ConversationApi.unmute(conversationId)
      commit(types.UNMUTE_CONVERSATION)
    } catch (error) {
      //
    }
  },

  sendEmailTranscript: async (_, { conversationId, email }) => {
    try {
      await ConversationApi.sendEmailTranscript({ conversationId, email })
    } catch (error) {
      throw new Error(error)
    }
  },

  updateCustomAttributes: async (
    { commit },
    { conversationId, customAttributes }
  ) => {
    try {
      const response = await ConversationApi.updateCustomAttributes({
        conversationId,
        customAttributes,
      })
      const { customAttributes } = response.data
      commit(types.UPDATE_CONVERSATION_CUSTOM_ATTRIBUTES, customAttributes)
    } catch (error) {
      // Handle error
    }
  },

  setConversationFilters ({ commit }, data) {
    commit(types.SET_CONVERSATION_FILTERS, data)
  },

  clearConversationFilters ({ commit }) {
    commit(types.CLEAR_CONVERSATION_FILTERS)
  },
  ...messageReadActions,
}

export default actions
